home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Science / RasMol2 / transfor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-28  |  46.7 KB  |  2,043 lines  |  [TEXT/KAHL]

  1. /* transfor.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, October 1994
  4.  * Version 2.5
  5.  */
  6. #include "rasmol.h"
  7.  
  8. #ifdef IBMPC
  9. #include <windows.h>
  10. #endif
  11. #ifdef APPLEMAC
  12. #ifdef __CONDITIONALMACROS__
  13. #include <Printing.h>
  14. #else
  15. #include <PrintTraps.h>
  16. #endif
  17. #include <Types.h>
  18. #endif
  19. #include <stdio.h>
  20. #include <math.h>
  21.  
  22. #define TRANSFORM
  23. #include "transfor.h"
  24. #include "molecule.h"
  25. #include "command.h"
  26. #include "abstree.h"
  27. #include "render.h"
  28. #include "graphics.h"
  29.  
  30.  
  31. typedef struct {
  32.         short col;
  33.         short shade;
  34.         unsigned char r;
  35.         unsigned char g;
  36.         unsigned char b;
  37.           } ShadeRef;
  38.  
  39.  
  40. #define CPKMAX  16
  41. static ShadeRef CPKShade[] = {
  42.      { 0, 0, 200, 200, 200 },       /*  0 Light Grey   */
  43.      { 0, 0, 143, 143, 255 },       /*  1 Sky Blue     */
  44.      { 0, 0, 240,   0,   0 },       /*  2 Red          */
  45.      { 0, 0, 255, 200,  50 },       /*  3 Yellow       */
  46.      { 0, 0, 255, 255, 255 },       /*  4 White        */
  47.      { 0, 0, 255, 192, 203 },       /*  5 Pink         */
  48.      { 0, 0, 218, 165,  32 },       /*  6 Golden Rod   */
  49.      { 0, 0,   0,   0, 255 },       /*  7 Blue         */
  50.      { 0, 0, 255, 165,   0 },       /*  8 Orange       */
  51.      { 0, 0, 128, 128, 144 },       /*  9 Dark Grey    */
  52.      { 0, 0, 165,  42,  42 },       /* 10 Brown        */
  53.      { 0, 0, 160,  32, 240 },       /* 11 Purple       */
  54.      { 0, 0, 255,  20, 147 },       /* 12 Deep Pink    */
  55.      { 0, 0,   0, 255,   0 },       /* 13 Green        */
  56.      { 0, 0, 178,  34,  34 },       /* 14 Fire Brick   */
  57.      { 0, 0,  34, 139,  34 } };     /* 15 Forest Green */
  58.  
  59.  
  60. static ShadeRef Shapely[] = {
  61.      { 0, 0, 140, 255, 140 },    /* ALA */
  62.      { 0, 0, 255, 255, 255 },    /* GLY */
  63.      { 0, 0,  69,  94,  69 },    /* LEU */
  64.      { 0, 0, 255, 112,  66 },    /* SER */
  65.      { 0, 0, 255, 140, 255 },    /* VAL */
  66.      { 0, 0, 184,  76,   0 },    /* THR */
  67.      { 0, 0,  71,  71, 184 },    /* LYS */
  68.      { 0, 0, 160,   0,  66 },    /* ASP */
  69.      { 0, 0,   0,  76,   0 },    /* ILE */
  70.      { 0, 0, 255, 124, 112 },    /* ASN */
  71.      { 0, 0, 102,   0,   0 },    /* GLU */
  72.      { 0, 0,  82,  82,  82 },    /* PRO */
  73.      { 0, 0,   0,   0, 124 },    /* ARG */
  74.      { 0, 0,  83,  76,  66 },    /* PHE */
  75.      { 0, 0, 255,  76,  76 },    /* GLN */
  76.      { 0, 0, 140, 112,  76 },    /* TYR */
  77.      { 0, 0, 112, 112, 255 },    /* HIS */
  78.      { 0, 0, 255, 255, 112 },    /* CYS */
  79.      { 0, 0, 184, 160,  66 },    /* MET */
  80.      { 0, 0,  79,  70,   0 },    /* TRP */
  81.  
  82.      { 0, 0, 255,   0, 255 },    /* ASX */
  83.      { 0, 0, 255,   0, 255 },    /* GLX */
  84.      { 0, 0, 255,   0, 255 },    /* PCA */
  85.      { 0, 0, 255,   0, 255 },    /* HYP */
  86.  
  87.      { 0, 0, 160, 160, 255 },    /*   A */
  88.      { 0, 0, 255, 140,  75 },    /*   C */
  89.      { 0, 0, 255, 112, 112 },    /*   G */
  90.      { 0, 0, 160, 255, 160 },    /*   T */
  91.  
  92.      { 0, 0, 184, 184, 184 },    /* 28 -> BackBone */
  93.      { 0, 0,  94,   0,  94 },    /* 29 -> Special  */
  94.      { 0, 0, 255,   0, 255 } };  /* 30 -> Default  */
  95.  
  96.      
  97. static ShadeRef AminoShade[] = {
  98.      { 0, 0, 230,  10,  10 },    /*  0  ASP, GLU      */
  99.      { 0, 0,  20,  90, 255 },    /*  1  LYS, ARG      */
  100.      { 0, 0, 130, 130, 210 },    /*  2  HIS           */
  101.      { 0, 0, 250, 150,   0 },    /*  3  SER, THR      */
  102.      { 0, 0,   0, 220, 220 },    /*  4  ASN, GLN      */
  103.      { 0, 0, 230, 230,   0 },    /*  5  CYS, MET      */
  104.      { 0, 0, 200, 200, 200 },    /*  6  ALA           */
  105.      { 0, 0, 235, 235, 235 },    /*  7  GLY           */
  106.      { 0, 0,  15, 130,  15 },    /*  8  LEU, VAL, ILE */
  107.      { 0, 0,  50,  50, 170 },    /*  9  PHE, TYR      */
  108.      { 0, 0, 180,  90, 180 },    /* 10  TRP           */
  109.      { 0, 0, 220, 150, 130 },    /* 11  PRO, PCA, HYP */
  110.      { 0, 0, 190, 160, 110 } };  /* 12  Others        */
  111.  
  112. static int AminoIndex[] = {
  113.       6, /*ALA*/   7, /*GLY*/   8, /*LEU*/   3,  /*SER*/
  114.       8, /*VAL*/   3, /*THR*/   1, /*LYS*/   0,  /*ASP*/
  115.       8, /*ILE*/   4, /*ASN*/   0, /*GLU*/  11,  /*PRO*/
  116.       1, /*ARG*/   9, /*PHE*/   4, /*GLN*/   9,  /*TYR*/
  117.       2, /*HIS*/   5, /*CYS*/   5, /*MET*/  10,  /*TRP*/
  118.       4, /*ASX*/   4, /*GLX*/  11, /*PCA*/  11   /*HYP*/
  119.               };
  120.  
  121. static ShadeRef HBondShade[] = {
  122.      { 0, 0, 255, 255, 255 },    /* 0  Offset =  2   */
  123.      { 0, 0, 255,   0, 255 },    /* 1  Offset =  3   */
  124.      { 0, 0, 255,   0,   0 },    /* 2  Offset =  4   */
  125.      { 0, 0, 255, 165,   0 },    /* 3  Offset =  5   */
  126.      { 0, 0,   0, 255, 255 },    /* 4  Offset = -3   */
  127.      { 0, 0,   0, 255,   0 },    /* 5  Offset = -4   */
  128.      { 0, 0, 255, 255,   0 } };  /* 6  Others        */
  129.  
  130.  
  131. static ShadeRef StructShade[] = {
  132.      { 0, 0, 255, 255, 255 },    /* 0  Default     */
  133.      { 0, 0, 240,   0, 128 },    /* 1  Alpha Helix */
  134.      { 0, 0, 255, 255,   0 },    /* 2  Beta Sheet  */
  135.      { 0, 0,  96, 128, 255 } };  /* 3  Turn        */
  136.  
  137. static ShadeRef PotentialShade[] = {
  138.      { 0, 0, 255,   0,   0 },    /* 0  Red     25 < V       */
  139.      { 0, 0, 255, 165,   0 },    /* 1  Orange  10 < V <  25 */
  140.      { 0, 0, 255, 255,   0 },    /* 2  Yellow   3 < V <  10 */
  141.      { 0, 0,   0, 255,   0 },    /* 3  Green    0 < V <   3 */
  142.      { 0, 0,   0, 255, 255 },    /* 4  Cyan    -3 < V <   0 */
  143.      { 0, 0,   0,   0, 255 },    /* 5  Blue   -10 < V <  -3 */
  144.      { 0, 0, 160,  32, 240 },    /* 6  Purple -25 < V < -10 */
  145.      { 0, 0, 255, 255, 255 } };  /* 7  White        V < -25 */
  146.  
  147.  
  148. /* Macros for commonly used loops */
  149. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  150.              for(group=chain->glist;group;group=group->gnext)    \
  151.              for(ptr=group->alist;ptr;ptr=ptr->anext)
  152. #define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext) 
  153. #define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
  154.              for(bptr=chain->blist;bptr;bptr=bptr->bnext)
  155.  
  156. #define MatchChar(a,b)   (((a)=='#')||((a)==(b)))
  157. #define RootSix          2.44948974278
  158.  
  159.  
  160. static ShadeRef ScaleRef[MAXSHADE];
  161. static int MaskColour[MAXMASK];
  162. static int MaskShade[MAXMASK];
  163. static int ScaleCount;
  164. static int LastShade;
  165.  
  166. static Real LastRX,LastRY,LastRZ;
  167. static Real Zoom;
  168.  
  169.  
  170.  
  171. void DetermineClipping()
  172. {
  173.     register int temp;
  174.     register int max;
  175.  
  176.     max = 0;
  177.     if( DrawAtoms && (MaxAtomRadius>max) )  max = MaxAtomRadius;
  178.     if( DrawBonds && (MaxBondRadius>max) )  max = MaxBondRadius;
  179.        
  180.     temp = ImageRadius + max;
  181.     UseScreenClip = (XOffset<temp) || (XOffset+temp>=XRange) ||
  182.             (YOffset<temp) || (YOffset+temp>=YRange);
  183. }
  184.  
  185.  
  186.  
  187. void SetRadiusValue( rad )
  188.     int rad;
  189. {
  190.     register int irad,change;
  191.     register Chain __far *chain;
  192.     register Group __far *group;
  193.     register Atom __far *ptr;
  194.  
  195.     if( !Database )
  196.     return;
  197.  
  198.     irad = (int)(Scale*rad);
  199.     MaxAtomRadius = 0;
  200.     DrawAtoms = False;
  201.     change = False;
  202.  
  203.     ForEachAtom
  204.     if( ptr->flag & SelectFlag )
  205.     {   if( irad>MaxAtomRadius )
  206.         MaxAtomRadius = irad;
  207.         ptr->flag |= SphereFlag;
  208.         ptr->radius = rad;
  209.         ptr->irad = irad;
  210.         change = True;
  211.     } else if( ptr->flag & SphereFlag )
  212.     {   DrawAtoms = True;
  213.         if( ptr->irad>MaxAtomRadius )
  214.         MaxAtomRadius = ptr->irad;
  215.     }
  216.  
  217.     if( change )
  218.     {   DrawAtoms = True;
  219.     DetermineClipping();
  220.     VoxelsClean = False;
  221.     BucketFlag = False;
  222.     }
  223. }
  224.  
  225. void SetRadiusTemperature()
  226. {
  227.     register int rad,irad,change;
  228.     register Chain __far *chain;
  229.     register Group __far *group;
  230.     register Atom __far *ptr;
  231.  
  232.     if( !Database )
  233.     return;
  234.  
  235.     MaxAtomRadius = 0;
  236.     DrawAtoms = False;
  237.     change = False;
  238.  
  239.     ForEachAtom
  240.     if( (ptr->flag&SelectFlag) && (ptr->temp>0) )
  241.     {   rad = (5*ptr->temp)>>1;
  242.         if( rad>500 ) rad = 500;
  243.  
  244.         irad = (int)(Scale*rad);
  245.         if( irad>MaxAtomRadius )
  246.         MaxAtomRadius = irad;
  247.         ptr->flag |= SphereFlag;
  248.         ptr->radius = rad;
  249.         ptr->irad = irad;
  250.         change = True;
  251.     } else if( ptr->flag & SphereFlag )
  252.     {   DrawAtoms = True;
  253.         if( ptr->irad>MaxAtomRadius )
  254.         MaxAtomRadius = ptr->irad;
  255.     }
  256.  
  257.     if( change )
  258.     {   DrawAtoms = True;
  259.     DetermineClipping();
  260.     VoxelsClean = False;
  261.     BucketFlag = False;
  262.     }
  263. }
  264.  
  265.  
  266. void SetVanWaalRadius()
  267. {
  268.     register int rad,change;
  269.     register Chain __far *chain;
  270.     register Group __far *group;
  271.     register Atom __far *ptr;
  272.     register int elem;
  273.  
  274.     if( !Database )
  275.     return;
  276.  
  277.     MaxAtomRadius = 0;
  278.     DrawAtoms = False;
  279.     change = False;
  280.  
  281.     ForEachAtom
  282.     if( ptr->flag&SelectFlag )
  283.     {   elem = GetElemNumber(ptr);
  284.         rad = ElemVDWRadius(elem);
  285.         ptr->irad = (int)(Scale*rad);
  286.         ptr->radius = rad;
  287.         change = True;
  288.  
  289.         ptr->flag |=SphereFlag;
  290.         if( ptr->irad>MaxAtomRadius )
  291.         MaxAtomRadius = ptr->irad;
  292.     } else if( ptr->flag&SphereFlag )
  293.     {   DrawAtoms = True;
  294.         if( ptr->irad>MaxAtomRadius )
  295.         MaxAtomRadius = ptr->irad;
  296.     }
  297.  
  298.     if( change )
  299.     {   DrawAtoms = True;
  300.     DetermineClipping();
  301.     VoxelsClean = False;
  302.     BucketFlag = False;
  303.     }
  304. }
  305.  
  306.  
  307. void DisableSpacefill()
  308. {
  309.     register Chain __far *chain;
  310.     register Group __far *group;
  311.     register Atom __far *ptr;
  312.  
  313.     if( !Database || !DrawAtoms )
  314.     return;
  315.  
  316.     MaxAtomRadius = 0;
  317.     DrawAtoms = False;
  318.     
  319.     ForEachAtom
  320.     if( !(ptr->flag&SelectFlag) )
  321.     {   if( ptr->flag&SphereFlag )
  322.         {   if( ptr->irad>MaxAtomRadius )
  323.             MaxAtomRadius = ptr->irad;
  324.         DrawAtoms = True;
  325.         }
  326.     } else if( ptr->flag&SphereFlag )
  327.         ptr->flag &= ~SphereFlag;
  328.  
  329.     DetermineClipping();
  330.     VoxelsClean = False;
  331.     BucketFlag = False;
  332. }
  333.  
  334.  
  335.  
  336. void EnableWireFrame( depth, rad )
  337.     int depth, rad;
  338. {
  339.     register Bond __far *bptr;
  340.     register int flag, irad;
  341.  
  342.     if( !Database )
  343.     return;
  344.  
  345.     DrawBonds = False;
  346.     MaxBondRadius = 0;
  347.     irad = (int)(Scale*rad);
  348.  
  349.     ForEachBond
  350.     {   flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag
  351.                : bptr->dstatom->flag | bptr->srcatom->flag;
  352.  
  353.     if( flag&SelectFlag )
  354.     {   DrawBonds = True;
  355.         bptr->flag &= ~DrawBondFlag;
  356.         if( !depth )
  357.         {   if( irad>MaxBondRadius )
  358.             MaxBondRadius = irad;
  359.         bptr->flag |= CylinderFlag;
  360.         bptr->radius = rad;
  361.         bptr->irad = irad;
  362.         } else bptr->flag |= WireFlag;
  363.     } else if( bptr->flag&DrawBondFlag )
  364.     {    DrawBonds = True;
  365.          if( bptr->flag&CylinderFlag )
  366.          if( bptr->irad>MaxBondRadius )
  367.              MaxBondRadius = bptr->irad;
  368.     }
  369.     }
  370.     DetermineClipping();
  371. }
  372.  
  373.  
  374. void DisableWireFrame()
  375. {
  376.     register Bond __far *bptr;
  377.     register int flag;
  378.  
  379.     if( !Database || !DrawBonds )
  380.     return;
  381.  
  382.     DrawBonds = False;
  383.     MaxBondRadius = 0;
  384.  
  385.     ForEachBond
  386.     {   flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag
  387.                : bptr->dstatom->flag | bptr->srcatom->flag;
  388.  
  389.     if( flag&SelectFlag )
  390.     {   bptr->flag &= ~DrawBondFlag;
  391.     } else if( bptr->flag&DrawBondFlag )
  392.     {   DrawBonds = True;
  393.         if( bptr->flag&CylinderFlag )
  394.         if( bptr->irad>MaxBondRadius )
  395.             MaxBondRadius = bptr->irad;
  396.     }
  397.     }
  398.     DetermineClipping();
  399. }
  400.  
  401.  
  402. void EnableBackBone( depth, rad )
  403.     int depth, rad;
  404. {
  405.     register Chain __far *chain;
  406.     register Bond __far *bptr;
  407.     register int flag,irad;
  408.  
  409.     if( !Database )
  410.     return;
  411.  
  412.     irad = (int)(Scale*rad);
  413.  
  414.     ForEachBack
  415.     {   flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag
  416.                : bptr->dstatom->flag | bptr->srcatom->flag;
  417.  
  418.     if( flag&SelectFlag )
  419.     {   bptr->flag &= ~DrawBondFlag;
  420.         if( !depth )
  421.         {   bptr->flag |= CylinderFlag;
  422.         bptr->radius = rad;
  423.         bptr->irad = irad;
  424.         } else bptr->flag |= WireFlag;
  425.     } 
  426.     }
  427.     DetermineClipping();
  428. }
  429.  
  430.  
  431. void DisableBackBone()
  432. {
  433.     register Chain __far *chain;
  434.     register Bond __far *bptr;
  435.  
  436.     if( !Database )
  437.     return;
  438.  
  439.     if( ZoneBoth )
  440.     {   ForEachBack
  441.         if( (bptr->dstatom->flag&bptr->srcatom->flag) & SelectFlag )
  442.         bptr->flag &= ~DrawBondFlag;
  443.     } else ForEachBack
  444.     if( (bptr->dstatom->flag|bptr->srcatom->flag) & SelectFlag )
  445.         bptr->flag &= ~DrawBondFlag;
  446.     DetermineClipping();
  447. }
  448.  
  449.  
  450. void SetHBondStatus( hbonds, enable, rad )
  451.     int hbonds, enable, rad;
  452. {
  453.     register HBond __far *list;
  454.     register HBond __far *ptr;
  455.     register Atom __far *src;
  456.     register Atom __far *dst;
  457.     register int flag, irad;
  458.  
  459.     if( !Database )
  460.     return;
  461.  
  462.     if( hbonds )
  463.     {   if( enable && (InfoHBondCount<0) )
  464.         CalcHydrogenBonds();
  465.     list = Database->hlist;
  466.     } else 
  467.     {   if( enable && (InfoSSBondCount<0) )
  468.         FindDisulphideBridges();
  469.     list = Database->slist;
  470.     }
  471.  
  472.     irad = (int)(Scale*rad);
  473.     for( ptr=list; ptr; ptr=ptr->hnext )
  474.     {   src = ptr->src;  dst = ptr->dst;
  475.  
  476.     flag = ZoneBoth? src->flag&dst->flag : src->flag|dst->flag;
  477.     if( flag & SelectFlag ) 
  478.     {   ptr->flag &= ~DrawBondFlag;
  479.         if( enable )
  480.         {   if( rad )
  481.         {   ptr->flag |= CylinderFlag;
  482.             ptr->radius = rad;
  483.             ptr->irad = irad;
  484.         } else ptr->flag |= WireFlag;
  485.         }
  486.     }
  487.     }
  488. }
  489.  
  490.  
  491. void SetRibbonStatus( enable, flag, width )
  492.     int enable, flag, width;
  493. {
  494.     register Chain __far *chain;
  495.     register Group __far *group;
  496.     register Atom __far *ptr;
  497.  
  498.     if( !Database )
  499.     return;
  500.  
  501.     /* Ribbons already disabled! */
  502.     if( !enable && !DrawRibbon )
  503.     return;
  504.  
  505.     if( InfoHelixCount<0 )
  506.     DetermineStructure();
  507.  
  508.     DrawRibbon = False;
  509.     for( chain=Database->clist; chain; chain=chain->cnext )
  510.     for( group=chain->glist; group; group=group->gnext )
  511.         if( enable )
  512.         {   if( group->flag & (RibbonFlag|StrandFlag) )
  513.             DrawRibbon = True;
  514.         
  515.         for( ptr=group->alist; ptr; ptr=ptr->anext )
  516.             if( IsAlphaCarbon(ptr->refno) )
  517.             {   if( ptr->flag&SelectFlag )
  518.             {   group->flag &= ~(RibbonFlag|StrandFlag);
  519.                 group->flag |= flag;
  520.                 if( !width )
  521.                 {   if( group->struc & (HelixFlag|SheetFlag) )
  522.                 {      group->width = 380;
  523.                 } else group->width = 100;
  524.                 } else group->width = width;
  525.                 DrawRibbon = True;
  526.             }
  527.             break;
  528.  
  529.             } else if( IsSugarPhosphate(ptr->refno) )
  530.             {   if( ptr->flag&SelectFlag )
  531.             {   group->width = width? width : 720;
  532.                 group->flag |= flag;
  533.                 DrawRibbon = True;
  534.             }
  535.             break;
  536.             }
  537.  
  538.  
  539.         } else  /* Disable Ribbon */
  540.         if( group->flag & (RibbonFlag|StrandFlag) )
  541.         {   for( ptr=group->alist; ptr; ptr=ptr->anext )
  542.             if( IsAlphaCarbon(ptr->refno) ||
  543.                 IsSugarPhosphate(ptr->refno) )
  544.             {   if( ptr->flag&SelectFlag )
  545.                 group->flag &= ~(RibbonFlag|StrandFlag);
  546.                 break;
  547.             }
  548.             if( group->flag & (RibbonFlag|StrandFlag) ) 
  549.             DrawRibbon = True;
  550.         }
  551. }
  552.  
  553.  
  554. void SelectZone( mask )
  555.     int mask;
  556. {
  557.     register Bond __far *bptr;
  558.     register Chain __far *chain;
  559.     register Group __far *group;
  560.     register Atom __far *ptr;
  561.  
  562.     if( !Database )
  563.     return;
  564.  
  565.     SelectCount = 0;
  566.     ForEachAtom
  567.     if( ptr->flag & mask )
  568.     {   ptr->flag |= SelectFlag;
  569.         SelectCount++;
  570.     } else ptr->flag &= ~SelectFlag;
  571.     DisplaySelectCount();
  572.  
  573.     if( ZoneBoth )
  574.     {   ForEachBond
  575.        if( (bptr->srcatom->flag&bptr->dstatom->flag) & SelectFlag )
  576.        {   bptr->flag |= SelectFlag;
  577.        } else bptr->flag &= ~SelectFlag;
  578.     } else
  579.     ForEachBond
  580.        if( (bptr->srcatom->flag|bptr->dstatom->flag) & SelectFlag )
  581.        {   bptr->flag |= SelectFlag;
  582.        } else bptr->flag &= ~SelectFlag;
  583.  
  584. }
  585.  
  586.  
  587. void RestrictZone( mask )
  588.     int mask;
  589. {
  590.     register Bond __far *bptr;
  591.     register Chain __far *chain;
  592.     register Group __far *group;
  593.     register Atom __far *ptr;
  594.     register int flag;
  595.  
  596.     if( !Database )
  597.     return;
  598.  
  599.     DrawAtoms = False;   MaxAtomRadius = 0;
  600.     DrawBonds = False;   MaxBondRadius = 0;
  601.     
  602.     SelectCount = 0;
  603.     ForEachAtom
  604.     if( ptr->flag & mask )
  605.     {   ptr->flag |= SelectFlag;
  606.         SelectCount++;
  607.  
  608.         if( ptr->flag & SphereFlag )
  609.         {   DrawAtoms = True;
  610.         if( ptr->irad>MaxAtomRadius )
  611.             MaxAtomRadius = ptr->irad;
  612.         }
  613.     } else ptr->flag &= ~(SelectFlag|SphereFlag);
  614.     DisplaySelectCount();
  615.     
  616.     ForEachBond
  617.     {   /* Ignore ZoneBoth setting! */
  618.     flag = bptr->dstatom->flag & bptr->srcatom->flag;
  619.     if( flag & SelectFlag )
  620.     {   bptr->flag |= SelectFlag;
  621.         if( bptr->flag&DrawBondFlag )
  622.         {   DrawBonds = True;
  623.         if( bptr->flag & CylinderFlag )
  624.             if( bptr->irad>MaxBondRadius )
  625.             MaxBondRadius = bptr->irad;
  626.         } 
  627.     } else bptr->flag &= ~(SelectFlag|DrawBondFlag);
  628.     }
  629.  
  630.     DetermineClipping();
  631.     VoxelsClean = False;
  632.     BucketFlag = False;
  633. }
  634.  
  635.  
  636.  
  637. int DefineShade( r, g, b )
  638.     unsigned char r, g, b;
  639. {
  640.     register int d,dr,dg,db;
  641.     register int dist,best;
  642.     register int i;
  643.  
  644.     /* Already defined! */
  645.     for( i=0; i<LastShade; i++ )
  646.     if( Shade[i].refcount )
  647.         if( (Shade[i].r==r)&&(Shade[i].g==g)&&(Shade[i].b==b) )
  648.         return(i);
  649.  
  650.     /* Allocate request */
  651.     for( i=0; i<LastShade; i++ )
  652.      if( !Shade[i].refcount )
  653.      {   Shade[i].r = r;
  654.          Shade[i].g = g;
  655.          Shade[i].b = b;
  656.          Shade[i].refcount = 0;
  657.          return(i);
  658.      }
  659.  
  660.     if( CommandActive )
  661.     WriteChar('\n');
  662.     WriteString("Warning: Unable to allocate shade!\n");
  663.     CommandActive = False;
  664.  
  665.     /* To avoid lint warning! */
  666.     best = dist = 0;
  667.  
  668.     /* Nearest match */
  669.     for( i=0; i<LastShade; i++ )
  670.     {   dr = Shade[i].r - r;
  671.     dg = Shade[i].g - g;
  672.     db = Shade[i].b - b;
  673.     d = dr*dr + dg*dg + db*db;
  674.     if( !i || (d<dist) )
  675.     {   dist = d;
  676.         best = i;
  677.     }
  678.     }
  679.     return( best );
  680. }
  681.  
  682.  
  683. void ScaleColourMap( count )
  684.     int count;
  685. {
  686.     register Real hue;
  687.     register int fract, sextant;
  688.     register int i, r, g, b;
  689.  
  690.     ScaleCount=0;
  691.     for( i=0; i<LastShade; i++ )
  692.     if( !Shade[i].refcount )
  693.         ScaleCount++;
  694.  
  695.     /* If there are no shades free! */
  696.     if( !ScaleCount ) ScaleCount = LastShade;
  697.  
  698.     if( count && (count<ScaleCount) )
  699.     ScaleCount = count;
  700.  
  701.     for( i=0; i<ScaleCount; i++ )
  702.     {   sextant = (int)(hue = (4.0*i)/(ScaleCount-1));
  703.     fract = (int)(255.0*(hue-sextant));
  704.  
  705.     switch( sextant )
  706.     {   case(0): r = 0;         g = fract;     b = 255;         break;
  707.         case(1): r = 0;         g = 255;       b = 255-fract;   break;
  708.         case(2): r = fract;     g = 255;       b = 0;           break;
  709.         case(3): r = 255;       g = 255-fract; b = 0;           break;
  710.         default: r = 255;       g = 0;         b = 0;
  711.     }
  712.     ScaleRef[i].r = r;
  713.     ScaleRef[i].g = g;
  714.     ScaleRef[i].b = b;
  715.     ScaleRef[i].shade = 0;
  716.     ScaleRef[i].col = 0;
  717.     }
  718. }
  719.  
  720.  
  721. static void SetLutEntry( i, r, g, b )
  722.     int i, r, g, b;
  723. {
  724.     ULut[i] = True;
  725.     RLut[i] = r;
  726.     GLut[i] = g;
  727.     BLut[i] = b;
  728.  
  729. #ifdef EIGHTBIT
  730.     Lut[i] = i;
  731. #else
  732.     Lut[i] = ( (Card)((r<<8)|g)<<8 ) | b;
  733. #endif
  734. }
  735.  
  736.  
  737. static Real Power( x, y )
  738.     Real x; int y;
  739. {
  740.     register Real result;
  741.  
  742.     result = x;
  743.     while( y>1 )
  744.     {   if( y&1 ) { result *= x; y--; }
  745.     else { result *= result; y>>=1; }
  746.     }
  747.     return( result );
  748. }
  749.  
  750.  
  751. void DefineColourMap()
  752. {
  753.     register Real diffuse;
  754.     register Real temp, inten;
  755.     register int col, r, g, b;
  756.     register int i, j, k;
  757.  
  758.     for( i=0; i<LutSize; i++ )
  759.     ULut[i] = False;
  760.  
  761.     if( !DisplayMode )
  762.     {   SetLutEntry(BackCol,BackR,BackG,BackB);
  763.     SetLutEntry(LabelCol,LabR,LabG,LabB);
  764.     SetLutEntry(BoxCol,BoxR,BoxG,BoxB);
  765.     } else SetLutEntry(BackCol,80,80,80);
  766.  
  767.  
  768.     diffuse = 1.0 - Ambient;
  769.     for( i=0; i<ColourDepth; i++ )
  770.     {   temp = (Real)i/ColourMask;
  771.     inten = diffuse*temp + Ambient;
  772.  
  773.     if( DisplayMode )
  774.     {   /* Unselected [40,40,255] */
  775.         /* Selected   [255,160,0]  */
  776.         r = (int)(255*inten);
  777.         g = (int)(160*inten);
  778.         b = (int)(40*inten);
  779.  
  780.         SetLutEntry( Shade2Colour(0)+i, b, b, r );
  781.         SetLutEntry( Shade2Colour(1)+i, r, g, 0 );
  782.  
  783.     } else 
  784.     {   if( FakeSpecular )
  785.         {   temp = Power(temp,SpecPower);
  786.         inten *= 1.0 - temp;
  787.         k = (int)(255*temp);
  788.         }
  789.  
  790.         for( j=0; j<LastShade; j++ )
  791.         if( Shade[j].refcount )
  792.         {   col = Shade2Colour(j);
  793.             r = (int)(Shade[j].r*inten); 
  794.             g = (int)(Shade[j].g*inten);
  795.             b = (int)(Shade[j].b*inten);
  796.  
  797.             if( FakeSpecular )
  798.             {   r += k;
  799.             g += k;
  800.             b += k;
  801.             }
  802.             SetLutEntry( col+i, r, g, b );
  803.         }
  804.     }
  805.     }
  806.  
  807.     if( Interactive )
  808.     AllocateColourMap();
  809. }
  810.  
  811.  
  812. void ResetColourMap()
  813. {
  814.     register int i;
  815.  
  816. #ifdef EIGHTBIT
  817.     for( i=0; i<256; i++ )
  818.     ULut[i] = False;
  819. #endif
  820.  
  821.     SpecPower = 8;
  822.     FakeSpecular = False;
  823.     Ambient = DefaultAmbient;
  824.     BackR = BackG = BackB = 0;
  825.     BoxR = BoxG = BoxB = 255;
  826.     LabR = LabG = LabB = 255;
  827.     for( i=0; i<LastShade; i++ )
  828.     Shade[i].refcount = 0;
  829.     ScaleCount = 0;
  830. }
  831.  
  832.  
  833. void ColourBondNone()
  834. {
  835.     register Bond __far *bptr;
  836.  
  837.     if( Database )
  838.     ForEachBond
  839.         if( (bptr->flag&SelectFlag) && bptr->col )
  840.         {   Shade[Colour2Shade(bptr->col)].refcount--;
  841.         bptr->col = 0;
  842.         }
  843. }
  844.  
  845.  
  846. void ColourBondAttrib( r, g, b )
  847.     int r, g, b;
  848. {
  849.     register Bond __far *bptr;
  850.     register int shade,col;
  851.  
  852.     if( Database )
  853.     {   ForEachBond
  854.         if( (bptr->flag&SelectFlag) && bptr->col )
  855.         Shade[Colour2Shade(bptr->col)].refcount--;
  856.  
  857.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  858.     col = Shade2Colour(shade);
  859.  
  860.     ForEachBond
  861.         if( bptr->flag&SelectFlag )
  862.         {   Shade[shade].refcount++;
  863.         bptr->col = col;
  864.         }
  865.     }
  866. }
  867.  
  868.  
  869. void ColourBackNone()
  870. {
  871.     register Chain __far *chain;
  872.     register Bond __far *bptr;
  873.     register int flag;
  874.  
  875.     if( Database )
  876.     ForEachBack
  877.     {   flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag
  878.                : bptr->dstatom->flag | bptr->srcatom->flag;
  879.  
  880.         if( flag&SelectFlag )
  881.         {   bptr->flag |= SelectFlag;
  882.         if( bptr->col )
  883.         {   Shade[Colour2Shade(bptr->col)].refcount--;
  884.             bptr->col = 0;
  885.         }
  886.         } else bptr->flag &= ~SelectFlag;
  887.     }
  888. }
  889.  
  890.  
  891. void ColourBackAttrib( r, g, b )
  892.     int r, g, b;
  893. {
  894.     register int shade,col;
  895.     register Chain __far *chain;
  896.     register Bond __far *bptr;
  897.  
  898.     if( Database )
  899.     {   ColourBackNone();
  900.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  901.     col = Shade2Colour(shade);
  902.  
  903.     ForEachBack
  904.         if( bptr->flag&SelectFlag )
  905.         {   Shade[shade].refcount++;
  906.         bptr->col = col;
  907.         }
  908.     }
  909. }
  910.  
  911.  
  912. void ColourHBondNone( hbonds )
  913.     int hbonds;
  914. {
  915.     register HBond __far *list;
  916.     register HBond __far *ptr;
  917.     register Atom __far *src;
  918.     register Atom __far *dst;
  919.  
  920.     if( !Database )
  921.     return;
  922.  
  923.     list = hbonds? Database->hlist : Database->slist;
  924.  
  925.     if( ZoneBoth )
  926.     {   for( ptr=list; ptr; ptr=ptr->hnext )
  927.     {   src = ptr->src;  dst = ptr->dst;
  928.  
  929.         if( (src->flag&dst->flag) & SelectFlag )
  930.         {   ptr->flag |= SelectFlag;
  931.         if( ptr->col )
  932.         {   Shade[Colour2Shade(ptr->col)].refcount--;
  933.             ptr->col = 0;
  934.         }
  935.         } else ptr->flag &= ~SelectFlag;
  936.     }
  937.     } else
  938.     for( ptr=list; ptr; ptr=ptr->hnext )
  939.     {   src = ptr->src;  dst = ptr->dst;
  940.  
  941.         if( (src->flag|dst->flag) & SelectFlag )
  942.         {   ptr->flag |= SelectFlag;
  943.         if( ptr->col )
  944.         {   Shade[Colour2Shade(ptr->col)].refcount--;
  945.             ptr->col = 0;
  946.         }
  947.         } else ptr->flag &= ~SelectFlag;
  948.     }
  949. }
  950.  
  951. void ColourHBondType()
  952. {
  953.     register HBond __far *ptr;
  954.     register ShadeRef *ref;
  955.     register int i;
  956.  
  957.     if( !Database ) return;
  958.     for( i=0; i<7; i++ )
  959.     HBondShade[i].col = 0;
  960.  
  961.     if( InfoHBondCount<0 )
  962.     {   CalcHydrogenBonds();
  963.     } else ColourHBondNone( True );
  964.  
  965.     for( ptr=Database->hlist; ptr; ptr=ptr->hnext )
  966.     if( ptr->flag & SelectFlag )
  967.     {   switch( ptr->offset )
  968.         {   case(  2 ):  ref = HBondShade;     break;
  969.         case(  3 ):  ref = HBondShade+1;   break;
  970.         case(  4 ):  ref = HBondShade+2;   break;
  971.         case(  5 ):  ref = HBondShade+3;   break;
  972.         case( -3 ):  ref = HBondShade+4;   break;
  973.         case( -4 ):  ref = HBondShade+5;   break;
  974.         default:     ref = HBondShade+6;   break;
  975.         }
  976.  
  977.         if( !ref->col )
  978.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  979.         ref->col = Shade2Colour(ref->shade);
  980.         }
  981.         Shade[ref->shade].refcount++;
  982.         ptr->col = (Byte)ref->col;
  983.     }
  984. }
  985.  
  986.  
  987. void ColourHBondAttrib( hbonds, r, g, b )
  988.     int hbonds, r, g, b;
  989. {
  990.     register HBond __far *list;
  991.     register HBond __far *ptr;
  992.     register int col,shade;
  993.  
  994.     if( !Database )
  995.     return;
  996.  
  997.     if( hbonds )
  998.     {   if( InfoHBondCount<0 )
  999.     {   CalcHydrogenBonds();
  1000.     } else ColourHBondNone(True);
  1001.     } else
  1002.     if( InfoSSBondCount<0 )
  1003.     {   FindDisulphideBridges();
  1004.     } else ColourHBondNone(False);
  1005.  
  1006.  
  1007.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1008.     col = Shade2Colour(shade);
  1009.  
  1010.     list = hbonds? Database->hlist : Database->slist;
  1011.     for( ptr=list; ptr; ptr=ptr->hnext )
  1012.     if( ptr->flag & SelectFlag )
  1013.     {   Shade[shade].refcount++;
  1014.         ptr->col = col;
  1015.     }
  1016. }
  1017.  
  1018.  
  1019. void ColourRibbonNone( flag )
  1020.     int flag;
  1021. {
  1022.     register Chain __far *chain;
  1023.     register Group __far *group;
  1024.     register Atom __far *aptr;
  1025.  
  1026.     if( !Database )
  1027.     return;
  1028.  
  1029.     if( InfoHelixCount<0 )
  1030.     return;
  1031.  
  1032.     for( chain=Database->clist; chain; chain=chain->cnext )
  1033.     for( group=chain->glist; group; group=group->gnext )
  1034.         if( (aptr=FindGroupAtom(group,1)) && (aptr->flag&SelectFlag) )
  1035.         {   if( (flag&RibColInside) && group->col1 )
  1036.         {   Shade[Colour2Shade(group->col1)].refcount--;
  1037.             group->col1 = 0;
  1038.         }
  1039.         if( (flag&RibColOutside) && group->col2 )
  1040.         {   Shade[Colour2Shade(group->col2)].refcount--;
  1041.             group->col2 = 0;
  1042.         }
  1043.         }
  1044. }
  1045.  
  1046.  
  1047. void ColourRibbonAttrib( flag, r, g, b )
  1048.     int flag, r, g, b;
  1049. {
  1050.     register int shade, col;
  1051.     register Chain __far *chain;
  1052.     register Group __far *group;
  1053.     register Atom __far *aptr;
  1054.  
  1055.     if( Database )
  1056.     {   if( InfoHelixCount >= 0 )
  1057.     {   ColourRibbonNone( flag );
  1058.     } else DetermineStructure();
  1059.  
  1060.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1061.     col = Shade2Colour(shade);
  1062.  
  1063.     for( chain=Database->clist; chain; chain=chain->cnext )
  1064.         for( group=chain->glist; group; group=group->gnext )
  1065.         if( (aptr=FindGroupAtom(group,1)) 
  1066.             && (aptr->flag&SelectFlag) )
  1067.         {   if( flag & RibColInside )
  1068.             {   Shade[shade].refcount++;
  1069.             group->col1 = col;
  1070.             }
  1071.             if( flag & RibColOutside )
  1072.             {   Shade[shade].refcount++;
  1073.             group->col2 = col;
  1074.             }
  1075.         }
  1076.     }
  1077. }
  1078.  
  1079.  
  1080. void ColourDotsAttrib( r, g, b )
  1081.     int r, g, b;
  1082. {
  1083.     register DotStruct __far *ptr;
  1084.     register int i,shade,col;
  1085.  
  1086.     if( Database )
  1087.     {   for( ptr=DotPtr; ptr; ptr=ptr->next )
  1088.         for( i=0; i<ptr->count; i++ )
  1089.         {    shade = Colour2Shade(ptr->col[i]);
  1090.          Shade[shade].refcount--;
  1091.         }
  1092.  
  1093.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1094.     col = Shade2Colour(shade);
  1095.     for( ptr=DotPtr; ptr; ptr=ptr->next )
  1096.         for( i=0; i<ptr->count; i++ )
  1097.         {   Shade[shade].refcount++;
  1098.         ptr->col[i] = col;
  1099.         }
  1100.     }
  1101. }
  1102.  
  1103.  
  1104. /* Coulomb's Law */
  1105. int CalculatePotential( x, y, z )
  1106.     Long x, y, z;
  1107. {
  1108.     register Chain __far *chain;
  1109.     register Group __far *group;
  1110.     register Atom __far *ptr;
  1111.     register Long dx,dy,dz;
  1112.     register Long result;
  1113.     register Card dist;
  1114.     register Card max;
  1115.  
  1116.  
  1117.     /* Calculated charges have b-values < 0.0     */
  1118.     /* if( MinFun(MinMainTemp,MinHetaTemp) >= 0 ) */
  1119.     /*     CalculateCharges();                    */
  1120.  
  1121.     /* 8.0 Angstrom Cut Off */
  1122.     max = (Long)2000*2000;
  1123.  
  1124.     result = 0;
  1125.     ForEachAtom
  1126.     {   dx = ptr->xorg-x;
  1127.     if( (dist=dx*dx) < max )
  1128.     {   dy = ptr->yorg - y;
  1129.         if( (dist+=dy*dy) < max )
  1130.         {   dz = ptr->zorg - z;
  1131.         if( (dist+=dz*dz) < max )
  1132.             result += ((Long)ptr->temp<<12) / isqrt(dist);
  1133.         }
  1134.     }
  1135.     }
  1136.     /* Dielectric Constant = 10.0 */
  1137.     /* (332.0*250.0)/(10.0*100.0) */
  1138.     result = ((Long)result*83) >> 12;
  1139.     return( (int)result );
  1140. }
  1141.  
  1142.  
  1143. void ColourDotsPotential()
  1144. {
  1145.     register DotStruct __far *ptr;
  1146.     register int i,shade,result;
  1147.     register ShadeRef *ref;
  1148.  
  1149.     if( Database )
  1150.     {   for( i=0; i<8; i++ )
  1151.         PotentialShade[i].col = 0;
  1152.  
  1153.     /* Colour Dots None! */
  1154.     for( ptr=DotPtr; ptr; ptr=ptr->next )
  1155.         for( i=0; i<ptr->count; i++ )
  1156.         {    shade = Colour2Shade(ptr->col[i]);
  1157.          Shade[shade].refcount--;
  1158.         }
  1159.  
  1160.     for( ptr=DotPtr; ptr; ptr=ptr->next )
  1161.         for( i=0; i<ptr->count; i++ )
  1162.         {   result = CalculatePotential( ptr->xpos[i],
  1163.                          ptr->ypos[i],
  1164.                          ptr->zpos[i] );
  1165.  
  1166.         /* Determine Colour Bucket */
  1167.         if( result >= 0 )
  1168.         {   if( result > 10 )
  1169.             {      if( result > 24 )
  1170.                {      ref = PotentialShade + 0;
  1171.                } else ref = PotentialShade + 1;
  1172.             } else if( result > 3 )
  1173.                {      ref = PotentialShade + 2;
  1174.                } else ref = PotentialShade + 3;
  1175.         } else 
  1176.             if( result > -10 )
  1177.             {      if( result > -3 )
  1178.                {      ref = PotentialShade + 4;
  1179.                } else ref = PotentialShade + 5;
  1180.             } else if( result > -24 )
  1181.                {      ref = PotentialShade + 6;
  1182.                } else ref = PotentialShade + 7;
  1183.  
  1184.         if( !ref->col )
  1185.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1186.             ref->col = Shade2Colour(ref->shade);
  1187.         }
  1188.         Shade[ref->shade].refcount++;
  1189.         ptr->col[i] = ref->col;
  1190.         }
  1191.     }
  1192. }
  1193.  
  1194.  
  1195. static void ResetColourAttrib()
  1196. {
  1197.     register Chain __far *chain;
  1198.     register Group __far *group;
  1199.     register Atom __far *ptr;
  1200.  
  1201.     ForEachAtom
  1202.     if( (ptr->flag&SelectFlag) && ptr->col )
  1203.         Shade[Colour2Shade(ptr->col)].refcount--;
  1204. }
  1205.  
  1206.  
  1207. void MonoColourAttrib( r, g, b )
  1208.     int r, g, b;
  1209. {
  1210.     register int shade,col;
  1211.     register Chain __far *chain;
  1212.     register Group __far *group;
  1213.     register Atom __far *ptr;
  1214.  
  1215.     if( Database )
  1216.     {   ResetColourAttrib();
  1217.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1218.     col = Shade2Colour(shade);
  1219.  
  1220.     ForEachAtom
  1221.         if( ptr->flag&SelectFlag )
  1222.         {   Shade[shade].refcount++;
  1223.         ptr->col = col;
  1224.         }
  1225.     }
  1226. }
  1227.  
  1228.  
  1229. void ScaleColourAttrib( attr )
  1230.     int attr;
  1231. {
  1232.     register ShadeRef *ref;
  1233.     register int count, attrno, factor;
  1234.     register Chain __far *chain;
  1235.     register Group __far *group;
  1236.     register Atom __far *ptr;
  1237.     register Long temp;
  1238.     register int i;
  1239.  
  1240.     if( !Database ) return;
  1241.  
  1242.     switch( attr )
  1243.     {   case(ChainAttr):   attrno = InfoChainCount;   
  1244.                factor = 1;
  1245.                break;
  1246.  
  1247.     case(GroupAttr):   factor = MinMainRes;
  1248.                attrno = MaxMainRes;
  1249.                if( HetaGroups && HetaGroupCount )
  1250.                {   if( MinHetaRes < factor )
  1251.                    factor = MinHetaRes;
  1252.                    if( MaxHetaRes > attrno )
  1253.                    attrno = MaxHetaRes;
  1254.                } 
  1255.                attrno -= (factor-1);
  1256.                break;
  1257.  
  1258.     case(ChargeAttr):
  1259.     case(TempAttr):    factor = MinMainTemp;
  1260.                attrno = MaxMainTemp;
  1261.                if( HetaGroups && HetaGroupCount )
  1262.                {   if( MinHetaTemp < factor )
  1263.                    factor = MinHetaTemp;
  1264.                    if( MaxHetaTemp > attrno )
  1265.                    attrno = MaxHetaTemp;
  1266.                }
  1267.                attrno -= (factor-1);
  1268.                break;
  1269.  
  1270.     default:           return;
  1271.     }
  1272.  
  1273.     if( attrno<2 )
  1274.     {   MonoColourAttrib(255,255,255);
  1275.     return;
  1276.     }
  1277.  
  1278.     ResetColourAttrib();
  1279.     ScaleColourMap(attrno);
  1280.  
  1281.     switch( attr )
  1282.     {    case(ChainAttr):
  1283.          count = 0;
  1284.          for( chain=Database->clist; chain; chain=chain->cnext )
  1285.          {   ref = &(ScaleRef[(count*ScaleCount)/attrno]);
  1286.              if( !(ref->col && Shade[ref->shade].refcount) )
  1287.              {   ref->shade = DefineShade(ref->r,ref->g,ref->b);
  1288.              ref->col = Shade2Colour(ref->shade);
  1289.              }
  1290.              for( group=chain->glist; group; group=group->gnext )
  1291.              for( ptr=group->alist; ptr; ptr=ptr->anext )
  1292.                  if( ptr->flag&SelectFlag )
  1293.                  {   Shade[ref->shade].refcount++;
  1294.                  ptr->col = ref->col;
  1295.                  }
  1296.              count++;
  1297.          }
  1298.          break;
  1299.  
  1300.  
  1301.      case(GroupAttr):
  1302.          for( chain=Database->clist; chain; chain=chain->cnext )
  1303.              for( group=chain->glist; group; group=group->gnext )
  1304.              {   temp = (Long)ScaleCount*(group->serno-factor);
  1305.              i = (int)(temp/attrno);
  1306.  
  1307.              if( i >= ScaleCount )
  1308.              {   ref = ScaleRef + (ScaleCount-1);
  1309.              } else if( i >= 0 )
  1310.              {   ref = ScaleRef + i;
  1311.              } else ref = ScaleRef;
  1312.  
  1313.              if( !(ref->col && Shade[ref->shade].refcount) )
  1314.              {   ref->shade = DefineShade(ref->r,ref->g,ref->b);
  1315.                  ref->col = Shade2Colour(ref->shade);
  1316.              }
  1317.  
  1318.              for( ptr=group->alist; ptr; ptr=ptr->anext )
  1319.                  if( ptr->flag&SelectFlag )
  1320.                  {   Shade[ref->shade].refcount++;
  1321.                  ptr->col = ref->col;
  1322.                  }
  1323.              }
  1324.          break;
  1325.  
  1326.  
  1327.      case(TempAttr):
  1328.          ForEachAtom
  1329.              if( ptr->flag&SelectFlag )
  1330.              {   i = (int)(((Long)ScaleCount*(ptr->temp-factor))
  1331.                     /attrno);
  1332.  
  1333.              if( i >= ScaleCount )
  1334.              {   ref = ScaleRef + (ScaleCount-1);
  1335.              } else if( i >= 0 )
  1336.              {   ref = ScaleRef + i;
  1337.              } else ref = ScaleRef;
  1338.  
  1339.              if( !(ref->col && Shade[ref->shade].refcount) )
  1340.              {   ref->shade = DefineShade(ref->r,ref->g,ref->b);
  1341.                  ref->col = Shade2Colour(ref->shade);
  1342.              }
  1343.              Shade[ref->shade].refcount++;
  1344.              ptr->col = ref->col;
  1345.              }
  1346.          break;
  1347.  
  1348.     case(ChargeAttr):
  1349.         ForEachAtom
  1350.              if( ptr->flag&SelectFlag )
  1351.              {   i = (int)(((Long)ScaleCount*(ptr->temp-factor))
  1352.                     /attrno);
  1353.  
  1354.              if( i <= 0 )
  1355.              {   ref = ScaleRef + (ScaleCount-1);
  1356.              } else if( i < ScaleCount )
  1357.              {   ref = ScaleRef + ((ScaleCount-1)-i);
  1358.              } else ref = ScaleRef;
  1359.  
  1360.              if( !(ref->col && Shade[ref->shade].refcount) )
  1361.              {   ref->shade = DefineShade(ref->r,ref->g,ref->b);
  1362.                  ref->col = Shade2Colour(ref->shade);
  1363.              }
  1364.              Shade[ref->shade].refcount++;
  1365.              ptr->col = ref->col;
  1366.              }
  1367.          break;
  1368.     }
  1369. }
  1370.  
  1371.  
  1372.  
  1373. static int MatchNumber( len, value, mask )
  1374.     int len, value;
  1375.     char *mask;
  1376. {
  1377.     register char digit, template;
  1378.     register int result;
  1379.     register int i;
  1380.  
  1381.     result = True;
  1382.     for( i=0; i<len; i++ )
  1383.     {   digit = (value%10) + '0';
  1384.     template = mask[len-i];
  1385.     if( template==' ' )
  1386.     {   if( value ) result = False;
  1387.     } else if( !MatchChar(template,digit) )
  1388.         result = False;
  1389.     value/=10;
  1390.     }
  1391.     return( result );
  1392. }
  1393.  
  1394.  
  1395. void UserMaskAttrib( fields )
  1396.     int fields;
  1397. {
  1398.     register MaskDesc *mptr;
  1399.     register char *temp, *name;
  1400.     register int shade, change;
  1401.     register int i, rad, match;
  1402.  
  1403.     register Chain __far *chain;
  1404.     register Group __far *group;
  1405.     register Atom __far *ptr;
  1406.  
  1407.  
  1408.     if( !Database ) return;
  1409.  
  1410.     if( !MaskCount )
  1411.     {   if( CommandActive )
  1412.         WriteChar('\n');
  1413.     WriteString("Warning: No user supplied colour records!\n");
  1414.     CommandActive = False;
  1415.     return;
  1416.     }
  1417.  
  1418.     change = False;
  1419.     ResetColourAttrib();
  1420.     if( fields&MaskColourFlag )
  1421.     for( i=0; i<MaskCount; i++ )
  1422.         MaskShade[i] = -1;
  1423.  
  1424.     if( fields&MaskRadiusFlag )
  1425.     {   MaxAtomRadius = 0;
  1426.     DrawAtoms = False;
  1427.     }
  1428.  
  1429.  
  1430.     ForEachAtom
  1431.     if( ptr->flag&SelectFlag )
  1432.     {   for( i=0; i<MaskCount; i++ )
  1433.     {   mptr = UserMask+i;
  1434.         temp = mptr->mask;
  1435.         match = True;
  1436.  
  1437.         if( !MatchChar(temp[13],chain->ident) ) match=False;
  1438.         if( !MatchChar(temp[9],ptr->altl) )     match=False;
  1439.  
  1440.         /* Atom Name */
  1441.         if( match )
  1442.         {   name = ElemDesc[ptr->refno];
  1443.         if( !MatchChar(temp[5],name[0]) ) match=False;
  1444.         if( !MatchChar(temp[6],name[1]) ) match=False;
  1445.         if( !MatchChar(temp[7],name[2]) ) match=False;
  1446.         if( !MatchChar(temp[8],name[3]) ) match=False;
  1447.         }
  1448.  
  1449.         /* Group Name */
  1450.         if( match )
  1451.         {   name = Residue[group->refno];
  1452.         if( !MatchChar(temp[10],name[0]) ) match=False;
  1453.         if( !MatchChar(temp[11],name[1]) ) match=False;
  1454.         if( !MatchChar(temp[12],name[2]) ) match=False;
  1455.         }
  1456.  
  1457.  
  1458.         if( match && (mptr->flags&SerNoFlag) )
  1459.         match = MatchNumber(4,ptr->serno,&temp[0]);
  1460.         if( match && (mptr->flags&ResNoFlag) )
  1461.         match = MatchNumber(3,group->serno,&temp[14]);
  1462.         if( match ) break;
  1463.     }
  1464.  
  1465.     if( fields&MaskColourFlag )
  1466.     {   if( match )
  1467.         {   if( MaskShade[i] == -1 )
  1468.         {   MaskShade[i] = DefineShade(mptr->r,mptr->g,mptr->b);
  1469.             MaskColour[i] = Shade2Colour(MaskShade[i]);
  1470.         }
  1471.         Shade[MaskShade[i]].refcount++;
  1472.         ptr->col = MaskColour[i];
  1473.         } else
  1474.         {   shade = DefineShade(255,255,255);
  1475.         ptr->col = Shade2Colour(shade);
  1476.         Shade[shade].refcount++;
  1477.         }
  1478.     }
  1479.  
  1480.     if( fields&MaskRadiusFlag )
  1481.     {   rad = match? mptr->radius : 375;
  1482.         ptr->irad = (int)(Scale*rad);
  1483.         ptr->flag |= SphereFlag;
  1484.         ptr->radius = rad;
  1485.  
  1486.         if( ptr->irad>MaxAtomRadius )
  1487.         MaxAtomRadius = ptr->irad;
  1488.         change = True;
  1489.     }
  1490.     } else if( ptr->flag&SphereFlag )
  1491.     {   DrawAtoms = True;
  1492.     if( ptr->irad>MaxAtomRadius )
  1493.         MaxAtomRadius = ptr->irad;
  1494.     }
  1495.  
  1496.     if( change )
  1497.     {   DrawAtoms = True;
  1498.     DetermineClipping();
  1499.     VoxelsClean = False;
  1500.     BucketFlag = False;
  1501.     }
  1502. }
  1503.  
  1504.  
  1505. void CPKColourAttrib()
  1506. {
  1507.     register ShadeRef *ref;
  1508.     register Chain __far *chain;
  1509.     register Group __far *group;
  1510.     register Atom __far *ptr;
  1511.     register int i;
  1512.  
  1513.     if( !Database ) return;
  1514.     for( i=0; i<CPKMAX; i++ )
  1515.     CPKShade[i].col = 0;
  1516.     ResetColourAttrib();
  1517.  
  1518.  
  1519.     ForEachAtom
  1520.     if( ptr->flag&SelectFlag )
  1521.     {   i = GetElemNumber( ptr );
  1522.         ref = CPKShade + Element[i].cpkcol;
  1523.  
  1524.         if( !ref->col )
  1525.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1526.         ref->col = Shade2Colour(ref->shade);
  1527.         }
  1528.         Shade[ref->shade].refcount++;
  1529.         ptr->col = ref->col;
  1530.     }
  1531. }
  1532.  
  1533.  
  1534. void AminoColourAttrib()
  1535. {
  1536.     register ShadeRef *ref;
  1537.     register Chain __far *chain;
  1538.     register Group __far *group;
  1539.     register Atom __far *ptr;
  1540.     register int i;
  1541.  
  1542.     if( !Database ) return;
  1543.     for( i=0; i<13; i++ )
  1544.     AminoShade[i].col = 0;
  1545.     ResetColourAttrib();
  1546.  
  1547.     ForEachAtom
  1548.     if( ptr->flag&SelectFlag )
  1549.     {   if( IsAmino(group->refno) )
  1550.         {   ref = AminoShade + AminoIndex[group->refno];
  1551.         } else ref = AminoShade+12;
  1552.  
  1553.         if( !ref->col )
  1554.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1555.         ref->col = Shade2Colour(ref->shade);
  1556.         }
  1557.         Shade[ref->shade].refcount++;
  1558.         ptr->col = ref->col;
  1559.     }
  1560. }
  1561.  
  1562.  
  1563. void ShapelyColourAttrib()
  1564. {
  1565.     register ShadeRef *ref;
  1566.     register Chain __far *chain;
  1567.     register Group __far *group;
  1568.     register Atom __far *ptr;
  1569.     register int i;
  1570.  
  1571.     if( !Database ) return;
  1572.     for( i=0; i<30; i++ )
  1573.     Shapely[i].col = 0;
  1574.     ResetColourAttrib();
  1575.  
  1576.     ForEachAtom
  1577.     if( ptr->flag&SelectFlag )
  1578.     {   if( IsAminoNucleo(group->refno) )
  1579.         {   ref = Shapely + group->refno;
  1580.         } else ref = Shapely+30;
  1581.  
  1582. /*  Original Colour Scheme
  1583.  *
  1584.  *  ref = &(Shapely[26]);
  1585.  *  if( IsNucleo(group->refno) )
  1586.  *  {   ref = Shapely + group->refno;
  1587.  *  } else if( IsShapelyBackbone(ptr->refno) )
  1588.  *  {   ref = &(Shapely[24]);
  1589.  *  } else if( IsShapelySpecial(ptr->refno) )
  1590.  *  {   ref = &(Shapely[25]);
  1591.  *  } else if( IsAmino(group->refno) )
  1592.  *      ref = Shapely + group->refno;
  1593.  */
  1594.  
  1595.         if( !ref->col )
  1596.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1597.         ref->col = Shade2Colour(ref->shade);
  1598.         }
  1599.         Shade[ref->shade].refcount++;
  1600.         ptr->col = ref->col;
  1601.     }
  1602. }
  1603.  
  1604.  
  1605. void StructColourAttrib()
  1606. {
  1607.     register ShadeRef *ref;
  1608.     register Chain __far *chain;
  1609.     register Group __far *group;
  1610.     register Atom __far *ptr;
  1611.     register int i;
  1612.  
  1613.     if( !Database )
  1614.     return;
  1615.  
  1616.     if( InfoHelixCount<0 )
  1617.     DetermineStructure();
  1618.  
  1619.     for( i=0; i<4; i++ )
  1620.     StructShade[i].col = 0;
  1621.     ResetColourAttrib();
  1622.  
  1623.     ForEachAtom
  1624.     if( ptr->flag&SelectFlag )
  1625.     {   if( group->struc & HelixFlag )
  1626.         {   ref = StructShade+1;
  1627.         } else if( group->struc & SheetFlag )
  1628.         {   ref = StructShade+2;
  1629.         } else if( group->struc & TurnFlag )
  1630.         {   ref = StructShade+3;
  1631.         } else ref = StructShade;
  1632.  
  1633.         if( !ref->col )
  1634.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1635.         ref->col = Shade2Colour(ref->shade);
  1636.         }
  1637.         Shade[ref->shade].refcount++;
  1638.         ptr->col = ref->col;
  1639.     }
  1640. }
  1641.  
  1642.  
  1643.  
  1644. int IsCPKColour( ptr )
  1645.     Atom __far *ptr;
  1646. {
  1647.     register ShadeRef *cpk;
  1648.     register ShadeDesc *col;
  1649.     register int elem;
  1650.  
  1651.     elem = GetElemNumber( ptr );
  1652.     cpk = CPKShade + Element[elem].cpkcol;
  1653.     col = Shade + Colour2Shade(ptr->col);
  1654.     return( (col->r==cpk->r) && 
  1655.         (col->g==cpk->g) && 
  1656.         (col->b==cpk->b) );
  1657. }
  1658.  
  1659.  
  1660. int IsVDWRadius( ptr )
  1661.     Atom __far *ptr;
  1662. {
  1663.     register int elem, rad;
  1664.  
  1665.     if( ptr->flag & SphereFlag )
  1666.     {   elem = GetElemNumber( ptr );
  1667.     rad = ElemVDWRadius( elem );
  1668.     return( ptr->radius == rad );
  1669.     } else return( False );
  1670. }
  1671.  
  1672.  
  1673.  
  1674. void InitialTransform()
  1675. {
  1676.     register Card dist;
  1677.     register Long x, y, z;
  1678.     register Long dx, dy, dz;
  1679.     register Card ax, ay, az;
  1680.     register Chain __far *chain;
  1681.     register Group __far *group;
  1682.     register Atom __far *ptr;
  1683.  
  1684.  
  1685.     dx = MaxX-MinX;   OrigCX = (dx>>1)+MinX;
  1686.     dy = MaxY-MinY;   OrigCY = (dy>>1)+MinY;
  1687.     dz = MaxZ-MinZ;   OrigCZ = (dz>>1)+MinZ;
  1688.  
  1689.     MaxX -= OrigCX;   MinX -= OrigCX;
  1690.     MaxY -= OrigCY;   MinY -= OrigCY;
  1691.     MaxZ -= OrigCZ;   MinZ -= OrigCZ;
  1692.  
  1693.     WorldRadius = 0;
  1694.     SideLen = MaxFun(dx,dy);
  1695.     if( dz>SideLen ) SideLen = dz;
  1696.     SideLen += 1000;  Offset = SideLen>>1;
  1697.     XOffset = WRange;  YOffset = HRange;
  1698.     ZOffset = 10000;
  1699.  
  1700.     ForEachAtom
  1701.     {   x = ptr->xorg-OrigCX;   ptr->xorg = x;  ax = (Card)AbsFun(x);
  1702.     y = ptr->yorg-OrigCY;   ptr->yorg = y;  ay = (Card)AbsFun(y);
  1703.     z = ptr->zorg-OrigCZ;   ptr->zorg = z;  az = (Card)AbsFun(z);
  1704.     dist = ax*ax + ay*ay + az*az;
  1705.     if( dist>WorldRadius )
  1706.         WorldRadius = dist;
  1707.     }
  1708.  
  1709.     WorldRadius = (Card)sqrt((double)WorldRadius);
  1710.     WorldSize = WorldRadius<<1;
  1711.     DScale = 1.0/(WorldSize+1000);
  1712.  
  1713.     /* MaxZoom*DScale*Range*500 == 118 */
  1714.     MaxZoom = 0.236*(WorldSize+1000)/Range;
  1715.     if( MaxZoom < 1.0 )
  1716.     {   DScale *= MaxZoom;
  1717.     MaxZoom = 1.0;
  1718.     }
  1719.     ZoomRange = Range;
  1720.     MaxZoom -= 1.0;
  1721. }
  1722.  
  1723.  
  1724. void ReviseInvMatrix()
  1725. {
  1726.     InvX[0] = IScale*RotX[0];
  1727.     InvX[1] = IScale*RotY[0];
  1728.     InvX[2] = IScale*RotZ[0];
  1729.  
  1730.     InvY[0] = IScale*RotX[1];
  1731.     InvY[1] = IScale*RotY[1];
  1732.     InvY[2] = IScale*RotZ[1];
  1733.  
  1734.     InvZ[0] = IScale*RotX[2];
  1735.     InvZ[1] = IScale*RotY[2];
  1736.     InvZ[2] = IScale*RotZ[2];
  1737.     ShadowTransform();
  1738. }
  1739.  
  1740.  
  1741. void PrepareTransform()
  1742. {
  1743.     register Real theta, temp;
  1744.     register Real cost, sint;
  1745.     register Real x, y, z;
  1746.     register Real ncost;
  1747.  
  1748.     if( (ReDrawFlag&RFRotateX) && (DialValue[0]!=LastRX) )
  1749.     {   theta = PI*(DialValue[0]-LastRX);
  1750.     cost = cos(theta);  sint = sin(theta);
  1751.     LastRX = DialValue[0];
  1752.  
  1753.     y=RotY[0]; z=RotZ[0];
  1754.     RotY[0]=cost*y+sint*z; 
  1755.     RotZ[0]=cost*z-sint*y;
  1756.  
  1757.     y=RotY[1]; z=RotZ[1];
  1758.     RotY[1]=cost*y+sint*z;
  1759.     RotZ[1]=cost*z-sint*y;
  1760.  
  1761.     y=RotY[2]; z=RotZ[2];
  1762.     RotY[2]=cost*y+sint*z;
  1763.     RotZ[2]=cost*z-sint*y;
  1764.  
  1765.     if( CenX || CenY || CenZ )
  1766.     {   ncost = 1.0-cost;
  1767.         temp =  CenX*(ncost*RotY[0] + sint*RotZ[0]);
  1768.         temp += CenY*(ncost*RotY[1] + sint*RotZ[1]);
  1769.         temp += CenZ*(ncost*RotY[2] + sint*RotZ[2]);
  1770.         temp = DialValue[5] - (Scale*temp)/YRange;
  1771.  
  1772.         if( temp < -1.0 )
  1773.         {   DialValue[5] = -1.0;
  1774.         } else if( temp > 1.0 )
  1775.         {   DialValue[5] = 1.0;
  1776.         } else DialValue[5] = temp;
  1777.     }
  1778.     }
  1779.  
  1780.     if( (ReDrawFlag&RFRotateY) && (DialValue[1]!=LastRY) )
  1781.     {   theta = PI*(DialValue[1]-LastRY);
  1782.     cost = cos(theta);  sint = sin(theta);
  1783.     LastRY = DialValue[1];
  1784.  
  1785.     x=RotX[0]; z=RotZ[0];
  1786.     RotX[0]=cost*x+sint*z;
  1787.     RotZ[0]=cost*z-sint*x;
  1788.  
  1789.     x=RotX[1]; z=RotZ[1];
  1790.     RotX[1]=cost*x+sint*z;
  1791.     RotZ[1]=cost*z-sint*x;
  1792.  
  1793.     x=RotX[2]; z=RotZ[2];
  1794.     RotX[2]=cost*x+sint*z;
  1795.     RotZ[2]=cost*z-sint*x;
  1796.  
  1797.     if( CenX || CenY || CenZ )
  1798.     {   ncost = 1.0-cost;
  1799.         temp =  CenX*(ncost*RotX[0] + sint*RotZ[0]);
  1800.         temp += CenY*(ncost*RotX[1] + sint*RotZ[1]);
  1801.         temp += CenZ*(ncost*RotX[2] + sint*RotZ[2]);
  1802.         temp = DialValue[4] - (Scale*temp)/XRange;
  1803.  
  1804.         if( temp < -1.0 )
  1805.         {   DialValue[4] = -1.0;
  1806.         } else if( temp > 1.0 )
  1807.         {   DialValue[4] = 1.0;
  1808.         } else DialValue[4] = temp;
  1809.     }
  1810.     }
  1811.  
  1812.     if( (ReDrawFlag&RFRotateZ) && (DialValue[2]!=LastRZ) )
  1813.     {   theta = PI*(DialValue[2]-LastRZ);
  1814.     cost = cos(theta);  sint = sin(theta);
  1815.     LastRZ = DialValue[2];
  1816.  
  1817.     x=RotX[0]; y=RotY[0];
  1818.     RotX[0]=cost*x-sint*y;
  1819.     RotY[0]=cost*y+sint*x;
  1820.  
  1821.     x=RotX[1]; y=RotY[1];
  1822.     RotX[1]=cost*x-sint*y;
  1823.     RotY[1]=cost*y+sint*x;
  1824.  
  1825.     x=RotX[2]; y=RotY[2];
  1826.     RotX[2]=cost*x-sint*y;
  1827.     RotY[2]=cost*y+sint*x;
  1828.  
  1829.     if( CenX || CenY || CenZ )
  1830.     {   ncost = 1.0-cost;
  1831.         temp =  CenX*(ncost*RotX[0] - sint*RotY[0]);
  1832.         temp += CenY*(ncost*RotX[1] - sint*RotY[1]);
  1833.         temp += CenZ*(ncost*RotX[2] - sint*RotY[2]);
  1834.         temp = DialValue[4] - (Scale*temp)/XRange;
  1835.  
  1836.         if( temp < -1.0 )
  1837.         {   DialValue[4] = -1.0;
  1838.         } else if( temp > 1.0 )
  1839.         {   DialValue[4] = 1.0;
  1840.         } else DialValue[4] = temp;
  1841.  
  1842.         ncost = 1.0-cost;
  1843.         temp =  CenX*(ncost*RotY[0] + sint*RotX[0]);
  1844.         temp += CenY*(ncost*RotY[1] + sint*RotX[1]);
  1845.         temp += CenZ*(ncost*RotY[2] + sint*RotX[2]);
  1846.         temp = DialValue[5] - (Scale*temp)/YRange;
  1847.  
  1848.         if( temp < -1.0 )
  1849.         {   DialValue[5] = -1.0;
  1850.         } else if( temp > 1.0 )
  1851.         {   DialValue[5] = 1.0;
  1852.         } else DialValue[5] = temp;
  1853.     }
  1854.     }
  1855. }
  1856.  
  1857.  
  1858. void ApplyTransform()
  1859. {
  1860.     register int temp;
  1861.     register Real x, y, z;
  1862.     register int oldx,oldy;
  1863.     register Chain __far *chain;
  1864.     register Group __far *group;
  1865.     register HBond __far *hptr;
  1866.     register Bond __far *bptr;
  1867.     register Atom __far *ptr;
  1868.  
  1869.  
  1870.     if( ReDrawFlag & RFMagnify )
  1871.     {   if( DialValue[3] <= 0.0 )
  1872.     {   Zoom = DialValue[3]+1.0;
  1873.         if( Zoom<0.1 ) Zoom=0.1;
  1874.     } else Zoom = (DialValue[3]*MaxZoom) + 1.0;
  1875.  
  1876.     Scale = Zoom*DScale*Range;
  1877.     ImageSize = (int)(Scale*WorldSize);
  1878.     ImageRadius = ImageSize>>1;
  1879.     IScale = 1.0/Scale;
  1880.  
  1881.     MaxAtomRadius = 0;
  1882.     MaxBondRadius = 0;
  1883.     }
  1884.  
  1885.     if( ReDrawFlag & RFRotate )
  1886.     {   PrepareTransform();
  1887.     if( UseShadow )
  1888.         ShadowTransform();
  1889.     }
  1890.  
  1891.     if( ReDrawFlag & (RFRotate|RFMagnify) )
  1892.     {   MatX[0] = Scale*RotX[0]; 
  1893.     MatX[1] = Scale*RotX[1];
  1894.     MatX[2] = Scale*RotX[2];
  1895.  
  1896.     MatY[0] = Scale*RotY[0];
  1897.     MatY[1] = Scale*RotY[1];
  1898.     MatY[2] = Scale*RotY[2];
  1899.  
  1900.     MatZ[0] = Scale*RotZ[0];
  1901.     MatZ[1] = Scale*RotZ[1];
  1902.     MatZ[2] = Scale*RotZ[2];
  1903.  
  1904.     if( UseShadow )
  1905.     {   InvX[0] = IScale*RotX[0]; 
  1906.         InvX[1] = IScale*RotY[0];
  1907.         InvX[2] = IScale*RotZ[0];
  1908.  
  1909.         InvY[0] = IScale*RotX[1];
  1910.         InvY[1] = IScale*RotY[1];
  1911.         InvY[2] = IScale*RotZ[1];
  1912.  
  1913.         InvZ[0] = IScale*RotX[2];
  1914.         InvZ[1] = IScale*RotY[2];
  1915.         InvZ[2] = IScale*RotZ[2];
  1916.     }
  1917.     }
  1918.  
  1919.     oldx = XOffset;
  1920.     oldy = YOffset;
  1921.     XOffset = WRange + (int)(DialValue[4]*XRange);
  1922.     YOffset = HRange + (int)(DialValue[5]*YRange);
  1923.  
  1924.     /* Zoom dependent Translation! */
  1925.     /* XOffset = WRange + (int)(DialValue[4]*ImageSize); */
  1926.     /* YOffset = HRange + (int)(DialValue[5]*ImageSize); */
  1927.  
  1928.  
  1929.     switch( ReDrawFlag )
  1930.     {   case(RFTransX):
  1931.         if( (temp = XOffset-oldx) ) 
  1932.             ForEachAtom ptr->x += temp;
  1933.         break;
  1934.  
  1935.     case(RFTransY):
  1936.         if( (temp = YOffset-oldy) ) 
  1937.             ForEachAtom ptr->y += temp;
  1938.         break;
  1939.  
  1940.     case(RFRotateX):
  1941.         ForEachAtom
  1942.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  1943.         ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
  1944.         ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
  1945.         }
  1946.         break;
  1947.  
  1948.     case(RFRotateY):
  1949.         ForEachAtom
  1950.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  1951.         ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
  1952.         ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
  1953.         }
  1954.         break;
  1955.  
  1956.     case(RFRotateZ):
  1957.         ForEachAtom
  1958.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  1959.         ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
  1960.         ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
  1961.         }
  1962.         break;
  1963.  
  1964.     default:
  1965.         if( DrawAtoms && (ReDrawFlag&RFMagnify) )
  1966.         {   ForEachAtom 
  1967.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  1968.             ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
  1969.             ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
  1970.             ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
  1971.             if( ptr->flag&SphereFlag )
  1972.             {   ptr->irad = (int)(Scale*ptr->radius);
  1973.             if( ptr->irad>MaxAtomRadius )
  1974.                 MaxAtomRadius = ptr->irad;
  1975.             }
  1976.         }
  1977.         } else
  1978.         ForEachAtom 
  1979.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  1980.             ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
  1981.             ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
  1982.             ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
  1983.         }
  1984.  
  1985.         if( ReDrawFlag & RFMagnify )
  1986.         {   if( DrawBonds )
  1987.             ForEachBond
  1988.             if( bptr->flag&CylinderFlag )
  1989.             {   bptr->irad = (int)(Scale*bptr->radius);
  1990.                 if( bptr->irad>MaxBondRadius )
  1991.                 MaxBondRadius = bptr->irad;
  1992.             }
  1993.  
  1994.         for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  1995.             if( hptr->flag&CylinderFlag )
  1996.             hptr->irad = (int)(Scale*hptr->radius);
  1997.  
  1998.         for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  1999.             if( hptr->flag&CylinderFlag )
  2000.             hptr->irad = (int)(Scale*hptr->radius);
  2001.  
  2002.         ForEachBack
  2003.             if( bptr->flag&CylinderFlag )
  2004.             bptr->irad = (int)(Scale*bptr->radius);
  2005.         }
  2006.     }
  2007.  
  2008.     DetermineClipping();
  2009.     if( UseScreenClip || ReDrawFlag!=RFRotateY )
  2010.     BucketFlag = False;
  2011. }
  2012.  
  2013.  
  2014. void ResetTransform()
  2015. {
  2016.     RotX[0] = 1.0;  RotX[1] = 0.0;  RotX[2] = 0.0;
  2017.     RotY[0] = 0.0;  RotY[1] = 1.0;  RotY[2] = 0.0;
  2018.     RotZ[0] = 0.0;  RotZ[1] = 0.0;  RotZ[2] = 1.0;
  2019.     LastRX = LastRY = LastRZ = 0.0;
  2020.     CenX = CenY = CenZ = 0;
  2021. }
  2022.  
  2023.  
  2024. void InitialiseTransform()
  2025. {
  2026.     ColourDepth = DefaultColDepth;
  2027.     ColourMask = ColourDepth-1;
  2028.  
  2029. #ifdef APPLEMAC
  2030.     LastShade = Colour2Shade(LutSize-1);
  2031. #else
  2032.     LastShade = Colour2Shade(LutSize);
  2033. #endif
  2034.  
  2035.     ResetColourMap();
  2036.     ResetTransform();
  2037.  
  2038.     ZoneBoth = True;
  2039.     HetaGroups = True;
  2040.     Hydrogens = True;
  2041. }
  2042.  
  2043.